package edu.cuit.zhuyimeng.aircraft.service.impl;

import com.alicp.jetcache.Cache;
import com.alicp.jetcache.CacheGetResult;
import com.alicp.jetcache.anno.CacheInvalidate;
import com.alicp.jetcache.anno.CacheInvalidateContainer;
import com.alicp.jetcache.anno.Cached;
import com.baomidou.dynamic.datasource.annotation.Master;
import com.baomidou.dynamic.datasource.annotation.Slave;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import edu.cuit.zhuyimeng.aircraft.controller.dto.CreateAircraftDTO;
import edu.cuit.zhuyimeng.aircraft.controller.vo.AircraftInfoVO;
import edu.cuit.zhuyimeng.aircraft.convert.AircraftConverter;
import edu.cuit.zhuyimeng.aircraft.dal.mapper.AircraftMapper;
import edu.cuit.zhuyimeng.aircraft.dal.mapper.AirlineMapper;
import edu.cuit.zhuyimeng.aircraft.dal.po.AircraftPO;
import edu.cuit.zhuyimeng.aircraft.dal.po.AirlinePO;
import edu.cuit.zhuyimeng.aircraft.enums.CacheConstants;
import edu.cuit.zhuyimeng.aircraft.service.IAircraftService;
import edu.cuit.zhuyimeng.framework.cache.aspect.annotation.CacheInvalidatePattern;
import edu.cuit.zhuyimeng.framework.common.exception.QueryException;
import edu.cuit.zhuyimeng.framework.common.exception.UpdateException;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 飞机服务实现类
 */
@Service
@RequiredArgsConstructor
public class AircraftService implements IAircraftService {

    private final Cache<Integer, List<Long>> aircraftPageCache;
    private final Cache<Long,AircraftInfoVO> aircraftInfoCache;
    private final Cache<String, List<Long>> allAircraftCache;

    private final AirlineMapper airlineMapper;
    private final AircraftMapper aircraftMapper;

    @Lazy
    @Autowired
    private IAircraftService aircraftService;

    @Override
    @CacheInvalidatePattern(name = CacheConstants.AIRCRAFT_INFO_PAGER,pattern = "*")
    @CacheInvalidate(name = CacheConstants.ALL_AIRCRAFT_INFO,key = "'all'")
    @Master
    public void addAircraft(CreateAircraftDTO createAircraftDTO) {

        AirlinePO airlinePO = airlineMapper.selectOneById(createAircraftDTO.getAirlineId());
        if (airlinePO == null) {
            throw new UpdateException("航空公司不存在");
        }

        AircraftPO aircraftPO = new AircraftPO();
        aircraftPO.setModel(createAircraftDTO.getModel());
        aircraftPO.setCapacity(createAircraftDTO.getCapacity());
        aircraftPO.setAirlineId(createAircraftDTO.getAirlineId());
        aircraftMapper.insert(aircraftPO);

        AircraftInfoVO aircraftInfoVO = AircraftConverter.convertToAircraftInfoVO(aircraftPO,airlinePO);
        aircraftInfoCache.put(aircraftInfoVO.getId(),aircraftInfoVO);

    }

    @Override
    @CacheInvalidatePattern(name = CacheConstants.AIRCRAFT_INFO_PAGER,pattern = "*")
    @CacheInvalidate(name = CacheConstants.ALL_AIRCRAFT_INFO,key = "'all'")
    @Master
    public void deleteAircraft(Long id) {
        int result = aircraftMapper.deleteById(id);
        if (result == 0) {
            throw new UpdateException("未查询到飞机");
        }
        aircraftInfoCache.remove(id);
    }

    @Override
    @CacheInvalidateContainer({
            @CacheInvalidate(name = CacheConstants.AIRCRAFT_INFO,key = "args[0]"),
            @CacheInvalidate(name = CacheConstants.ALL_AIRCRAFT_INFO,key = "'all'")
    })
    @Master
    public void lockAircraft(Long id) {
        int result = aircraftMapper.update(new LambdaUpdateWrapper<AircraftPO>().eq(AircraftPO::getId, id).set(AircraftPO::getLocked, true));
        if (result == 0) {
            throw new UpdateException("未查询到飞机");
        }
    }

    @Override
    @CacheInvalidateContainer({
            @CacheInvalidate(name = CacheConstants.AIRCRAFT_INFO,key = "args[0]"),
            @CacheInvalidate(name = CacheConstants.ALL_AIRCRAFT_INFO,key = "'all'")
    })
    @Master
    public void unlockAircraft(Long id) {
        int result = aircraftMapper.update(new LambdaUpdateWrapper<AircraftPO>().eq(AircraftPO::getId,id).set(AircraftPO::getLocked,false));
        if (result == 0) {
            throw new UpdateException("未查询到飞机");
        }
    }

    @Override
    @Cached(name = CacheConstants.AIRCRAFT_INFO,key = "args[0]")
    @Slave
    public AircraftInfoVO getAircraftInfo(Long id) {
        AircraftPO aircraftPO = getAndCheckAircraft(id);
        AirlinePO airlinePO = airlineMapper.selectOneById(aircraftPO.getAirlineId());
        return AircraftConverter.convertToAircraftInfoVO(aircraftPO,airlinePO);
    }

    @Override
//    @Cached(name = CacheConstants.AIRCRAFT_INFO_PAGER,key = "#page")
    @Slave
    public List<AircraftInfoVO> getAircraftList(Integer page) {
        CacheGetResult<List<Long>> queryResult = aircraftPageCache.GET(page);
        List<AircraftInfoVO> result;
        if (!queryResult.isSuccess()) {
            Page<AircraftPO> aircraftPage = new Page<>(page,20);
            List<AircraftPO> aircraftPOList = aircraftMapper.selectList(aircraftPage, new LambdaQueryWrapper<>());
            result =  aircraftPOList.stream().map(aircraftPO -> {
                AirlinePO airlinePO = airlineMapper.selectOneById(aircraftPO.getAirlineId());
                return AircraftConverter.convertToAircraftInfoVO(aircraftPO, airlinePO);
            }).toList();
            aircraftPageCache.put(page,aircraftPOList.stream().map(AircraftPO::getId).toList());
        } else {
            List<Long> value = queryResult.getValue();
            result = value.stream().map(id -> aircraftService.getAircraftInfo(id)).toList();
        }
        return result;
    }

    @Override
    @Cached(name = CacheConstants.ALL_AIRCRAFT_INFO,key = "'all'")
    @Slave
    public List<AircraftInfoVO> getAircraftList() {
        CacheGetResult<List<Long>> cacheGetResult = allAircraftCache.GET("all");
        if (cacheGetResult.isSuccess()) {
            return cacheGetResult.getValue().stream().map(id -> aircraftService.getAircraftInfo(id)).toList();
        } else {
            List<AircraftPO> aircraftPOList = aircraftMapper.selectList(new LambdaQueryWrapper<AircraftPO>().eq(AircraftPO::getLocked, 0));
            List<AircraftInfoVO> result = aircraftPOList.stream().map(aircraftPO -> {
                AirlinePO airlinePO = airlineMapper.selectOneById(aircraftPO.getAirlineId());
                return AircraftConverter.convertToAircraftInfoVO(aircraftPO, airlinePO);
            }).toList();
            allAircraftCache.put("all",result.stream().map(AircraftInfoVO::getId).toList());
            return result;
        }

    }

    @Override
    @Cached(name = CacheConstants.ALL_AIRLINE_INFO,key = "'all'")
    @Slave
    public List<AirlinePO> getAirlineList() {
        return airlineMapper.selectList(new LambdaQueryWrapper<>());
    }

    private AircraftPO getAndCheckAircraft(Long id) {
//        AircraftPO aircraftPO = aircraftMapper.selectOne(new LambdaQueryWrapper<AircraftPO>().eq(AircraftPO::getId, id));
        AircraftPO aircraftPO = aircraftMapper.selectOne(new QueryWrapper<AircraftPO>().eq("id",id));
        if (aircraftPO == null) {
            throw new QueryException("飞机不存在");
        }
        return aircraftPO;
    }

}
